--
-- @Author:      
-- @DateTime:    2018-03-30 23:05:48
-- @Description: 消息的派发

local skynet = require "skynet"
-- local queue = require "skynet.queue"
local proxypack = require "proxypack"
local pb = require 'protobuf'
local msgdef = require "msgdef"




local MessageDispatch = class("MessageDispatch")
---------------------------------------------------------
-- Private
---------------------------------------------------------
function MessageDispatch:ctor()

	self.tb_self_msg = {} --本服务要监听的消息
	-- self.mqueue = queue()	--消息队列
	self.all_msg_callback = nil --服务监听要中转的消息

	self:registerSelf('hotfix', handler(self,self.hotfixFile))	--热更文件
end

--注册本服务里的消息
function MessageDispatch:register(msg_name, callback)
	if not msg_name or not callback or type(callback) ~= 'function' then 
		dbglog("注册的函数回调不对___", msg_name)
		return
	end
	self.tb_self_msg[msg_name] = callback
end
function MessageDispatch:registerSelf(msg_name, callback)
	self:register(msg_name, callback)
end

function MessageDispatch:registerAll(callback)
	if not callback or type(callback) ~= 'function' then 
		dbglog("registerAll注册的函数回调不对___", type(callback))
		return
	end	
	self.all_msg_callback = callback
end
-- --消息进行队列化
-- function MessageDispatch:queueMessage(session, source, cmd, ...)		
-- 	local func = handler(self, self.dispatchMessage)
-- 	local result = self.mqueue(func,session, source, cmd, ...)
	
-- 	return result
-- end	

--服务器消息派发
function MessageDispatch:dispatchMessage(session, source, cmd, ... )
	-- dbglog("####dispatchMessage####### cmd=>", cmd, ...)
	local func = self.tb_self_msg[cmd] --
	if not func and not self.all_msg_callback then 
		dbglog("####### 消息没有注册### "..cmd .." not found at service ")
		return
	end
	
	if func then
		if not session and not source then 
			return func(...)
		end		
		local ok, res, res1 = xpcall(func, debug.traceback, ...)
		if ok then 
			-- print("______res__", res, type(res1))
			skynet.retpack(res, res1)	
		else
			errlog("______dispatchMessage___error______", cmd,  ok, res, res1)										
		end		
		return true
	end
	if self.all_msg_callback then 
		local ok, res, res1 = xpcall(self.all_msg_callback, debug.traceback, cmd, ...)
		if ok then 
			skynet.retpack(res, res1)	
		else
			errlog("______dispatchMessage____error_____", cmd,  ok, res)										
		end		
		return true		
	end
end

function MessageDispatch:get_msg_module_name(msgid)
    local m = msgdef.id_to_name[msgid]
    if not m then return end
    return m[1],m[2] --[1]->module,[2]->name
end


--消息来自客户端
function MessageDispatch:dispatchClientMessage(_,_,game_session,uid,data)
	
    local msg,size = proxypack.pack_raw(data)    
    local _,msgid,pbmsg,pbsize = proxypack.unpack_client_message(msg,size)
    local module, name = self:get_msg_module_name(msgid)
    if not module or not name then
        errlog('___invalid msgid',msgid, module, name)
        skynet.trash(msg,size)  --这里需要保证内存被释放
        return
    end
    local pbname = module .. '.' .. name
    local req_msg = pb.decode(pbname,pbmsg,pbsize)
    -- dbglog(string.format('[%s]>>>>>player[%s] got a request[%s] content(%s)',
    --     skynet.address(skynet.self()),tostring(uid),pbname,tostring_r(req_msg)))
    local func = self.tb_self_msg[name]
    if func then
	    local res, err = func(uid, game_session, req_msg)
	    if not res then
	        errlog(string.format('failed to handle requrest(%s.%s %d)',module,name, err or 0))
	    end
	    skynet.trash(msg,size)  --这里需要保证内存被释放
	    return true
	end

	if self.all_msg_callback then 
		local ok, res = xpcall(self.all_msg_callback, debug.traceback, cmd, data)
		if ok then 
			-- skynet.retpack(res)	
		else
			errlog("______dispatchClientMessage__error_______", cmd,  ok, res)										
		end		
		skynet.trash(msg,size)  --这里需要保证内存被释放
		return true		
	end

    skynet.trash(msg,size)  --这里需要保证内存被释放

end


--自己节点内消息派发
function MessageDispatch:dispatchSelfMessage(cmd, ... )

	-- dbglog("####dispatchSelfMessage#######", cmd, ...)
	local func = self.tb_self_msg[cmd] --
	if not func then 
		dbglog("####### cmd "..cmd .." not found at manager_service ")
		return
	end
	local res = nil
	local ok
	if type(func)=="function" then
		ok, res = xpcall(func, debug.traceback, ...)		
	end
	if not ok then 
		errlog("______dispatchSelfMessage_________", cmd,  ok, res)
	end
	
	return res
end


-- --需要排队的消息
-- function MessageDispatch:dispatchQueue()
-- 	return handler(self, self.queueMessage)
-- end

--lua消息的派发
function MessageDispatch:dispatchLua()
	return handler(self, self.dispatchMessage)
end

--client消息的派发
function MessageDispatch:dispatchClient()
	return handler(self, self.dispatchClientMessage)
end

function MessageDispatch:hotfixFile(file_name)
    dbglog("____hotfix_____", file_name)
    if global and global.hotfix then 
    	return global.hotfix:hotfixFile(file_name)
   	end
   	return true
end    

return MessageDispatch